package com.ply.flashsalessystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ply.flashsalessystem.entity.OrderRecord;
import com.ply.flashsalessystem.entity.pojo.Goods;
import com.ply.flashsalessystem.entity.pojo.OrderForGoods;
import com.ply.flashsalessystem.entity.pojo.OrderForGoodsDetaile;
import com.ply.flashsalessystem.entity.pojo.ShopCar;
import com.ply.flashsalessystem.entity.status.OrderDetailsStatus;
import com.ply.flashsalessystem.entity.status.OrderStatus;
import com.ply.flashsalessystem.entity.vo.store.OrderForStoreVo;
import com.ply.flashsalessystem.entity.wrapper.WrapperOrder;
import com.ply.flashsalessystem.exception.OrderException;
import com.ply.flashsalessystem.mapper.OrderForGoodsMapper;
import com.ply.flashsalessystem.mapper.OrderRecordMapper;
import com.ply.flashsalessystem.service.GoodsService;
import com.ply.flashsalessystem.service.OrderForGoodsDetaileService;
import com.ply.flashsalessystem.service.OrderForGoodsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ply.flashsalessystem.service.OrderRecordService;
import com.ply.flashsalessystem.utils.UserUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author XiaoPan
 * @since 2022-03-23
 */
@Service
@Slf4j
public class OrderForGoodsServiceImpl extends ServiceImpl<OrderForGoodsMapper, OrderForGoods> implements OrderForGoodsService {

    @Autowired
    OrderForGoodsMapper orderForGoodsMapper;

    @Autowired
    OrderRecordMapper orderRecordMapper;

    @Autowired
    GoodsService goodsService;

    @Autowired
    OrderForGoodsDetaileService orderForGoodsDetaileService;

    @Autowired
    OrderRecordService orderRecordService;


    /**
     * 分页条件查询 订单信息
     *
     * @param current      当前页
     * @param limit        每页的条数
     * @param wrapperOrder 查询条件
     * @return total: 总条数  rows: 总记录数
     */
    @Override
    public Page<OrderForStoreVo> queryOrder(Integer current, Integer limit, WrapperOrder wrapperOrder) {
        return orderForGoodsMapper.findAndPage(new Page<>(current, limit), wrapperOrder);
    }

    /**
     * 更新订单状态
     *
     * @param orderIdList 所有要修改的订单
     * @param status      要修改的状态
     * @return 修改成功 失败
     */
    @Override
    public boolean updateOrderStatusById(List<Integer> orderIdList, Integer status) {
        if (orderIdList == null || !statusLimit(status)) {
            return false;
        }
        //todo 批量更新 可以优化 sql 语句   在 xml 中 进行 foreach
        for (Integer ofgId : orderIdList) {
            boolean b = orderForGoodsMapper.updateStatusById(ofgId, status);
            // 一旦修改成功的话 就必须添加到 订单 状态修改 表中去
            if (b) {
                orderRecordMapper.addOrderRecord(ofgId, status);
            }
            log.info("{}:修改:{}", ofgId, b);
        }
        return true;
    }

    /**
     * 创建订单
     *
     * @param storeId 商家id
     * @param list    购物车列表
     *                先 创建 订单 表  获取 订单 id
     *                在 增加 订单详情表
     */
    @Override
    @Transactional
    public boolean createOrder(Long storeId, List<ShopCar> list) {
        log.info("创建订单 orderForGoodsService 中的 createOrder  开始");
        //创建 订单对象
        OrderForGoods orderForGoods = new OrderForGoods();

        // OrderForGoods 对象初始化
        orderForGoods.setUserId(UserUtils.getUserId());
        orderForGoods.setStatus(OrderStatus.NO_PAY);
        orderForGoods.setStoreId(storeId);

        double amountDue = 0;

        List<OrderForGoodsDetaile> list1 = new ArrayList<>();

        for (ShopCar shopCar : list) {
            //获取物品id
            Integer goodsId = shopCar.getGoodsId();
            // 生成 对象
            Goods good = goodsService.getById(goodsId);
//            通过商品 拿到价格
            double price = good.getPrice();
            // 拿到商品数量
            Double goodsNum = shopCar.getGoodsNum();

            OrderForGoodsDetaile orderForGoodsDetails = new OrderForGoodsDetaile();
            // 这里 少了 订单id 需要 在
            orderForGoodsDetails.setGoodsId(goodsId);
            //详情 状态 未分拣
            orderForGoodsDetails.setStatus(OrderDetailsStatus.No_Pickup);

            orderForGoodsDetails.setGoodsOrderNums(goodsNum);
            orderForGoodsDetails.setAmountDue(goodsNum * price);

            // 增加折扣 后修改
            orderForGoodsDetails.setAmountOriginal(goodsNum * price);
            orderForGoodsDetails.setPrice(price);

            list1.add(orderForGoodsDetails);

            amountDue += (goodsNum * price);
            log.debug("amountDue: {}", amountDue);
        }
        orderForGoods.setAmountDue(amountDue);
        //todo 折扣在这里判断 判断总价格


        log.debug("orderForGoods对象:{}", orderForGoods);
        orderForGoodsMapper.addOrder(orderForGoods);
        log.debug("订单id:{}", orderForGoods.getOfgId());

        for (OrderForGoodsDetaile orderForGoodsDetails : list1) {
            orderForGoodsDetails.setOfgId(orderForGoods.getOfgId());
        }
        // 在 订单详情表中 增加
        boolean b = orderForGoodsDetaileService.saveBatch(list1);

        OrderRecord orderRecord = new OrderRecord();
        orderRecord.setOfgId(orderForGoods.getOfgId());
        orderRecord.setStatus(orderForGoods.getStatus());

        //在 订单记录 增加
        orderRecordService.save(orderRecord);

        log.info("创建订单 orderForGoodsService 中的 createOrder  结束");
        return true;
    }


    /**
     * 订单详情 状态 改变   未打包  ->  打包
     */
    @Override
    @Transactional
    public boolean updateStatusToPicket(Integer org_d_id, double goodsNums) {
        OrderForGoodsDetaile orderForGoodsDetaile = orderForGoodsDetaileService.getById(org_d_id);
        if (!Objects.equals(orderForGoodsDetaile.getStatus(), OrderDetailsStatus.No_Pickup)) {
           throw new OrderException("订单 错误");
        }
        //只能 比 订单 数量少
        if (orderForGoodsDetaile.getGoodsOrderNums() < goodsNums){
            throw new OrderException("订单 数量 错误 , 暂时 只能 分拣 数量 比订单 少的");
        }

        // 这里不需要修改  修改订单详情 后面修改了 状态
//        orderForGoodsDetaileService.updateOrderForGoodsDetailsStatus(org_d_id, OrderDetailsStatus.Do_Pickup);
        orderForGoodsDetaile.setStatus(OrderDetailsStatus.Do_Pickup);
        orderForGoodsDetaile.setGoodsRealNums(goodsNums);
        double price = orderForGoodsDetaile.getAmountDue() / orderForGoodsDetaile.getGoodsOrderNums();

        orderForGoodsDetaile.setAmountPaid(price * goodsNums);
        // 在商品确认收货的时候 退钱
        orderForGoodsDetaile.setAmountReturn(orderForGoodsDetaile.getAmountDue() - (price * goodsNums));

        orderForGoodsDetaileService.updateById(orderForGoodsDetaile);

        //判断这个订单中还有详情表 有没有被打包的  DO_SORT
        Integer ofgId = orderForGoodsDetaile.getOfgId();
        QueryWrapper<OrderForGoodsDetaile> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ofg_id", ofgId);
        queryWrapper.eq("status", OrderDetailsStatus.No_Pickup);
        List<OrderForGoodsDetaile> list = orderForGoodsDetaileService.list(queryWrapper);

        if (list.isEmpty()) {
            //该订单打包完成 修改订单状态 分拣完成
            statusToDelivery(ofgId);

            // 修改 订单的  实付金额  退款金额
            queryWrapper.clear();
            queryWrapper.eq("ofg_id", ofgId);
            List<OrderForGoodsDetaile> list1 = orderForGoodsDetaileService.list(queryWrapper);
            double amountPaid = 0;
            double amountReturn = 0;

            for (OrderForGoodsDetaile forGoodsDetaile : list1) {
                amountPaid += forGoodsDetaile.getAmountPaid();
                amountReturn += forGoodsDetaile.getAmountReturn();
            }
            // 执行修改
            OrderForGoods orderForGoods = orderForGoodsMapper.selectByOfgId(ofgId);
            orderForGoods.setAmountPaid(amountPaid);
            orderForGoods.setAmountReturn(amountReturn);
            if (orderForGoodsMapper.updateById(orderForGoods) == 0){
                throw new RuntimeException("修改订单 实付金额  退款金额 失败");
            }

        }
        return true;
    }

    /**
     * 用户手动调用 取消订单
     * @param ofgID
     */
    @Override
    public void userCancelOrder(Integer ofgID) {
        OrderForGoods orderForGoods = orderForGoodsMapper.selectById(ofgID);
        if (!Objects.equals(orderForGoods.getUserId(), UserUtils.getUserId())) {
            throw new OrderException("订单号 错误");
        }
        cancelOrder(ofgID);
    }

    /**
     * 定时器 调用 的 取消订单
     *
     * @param ofgID 订单id
     */
    @Override
    public void cancelOrder(Integer ofgID) {
        // 取消订单
        statusToChanel(ofgID);

        //将订单的数据 恢复 到 库存中
        //查询 所有 订单详情
        QueryWrapper<OrderForGoodsDetaile> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ofg_id", ofgID);
        List<OrderForGoodsDetaile> list = orderForGoodsDetaileService.list(queryWrapper);
        for (OrderForGoodsDetaile orderForGoodsDetaile : list) {
            double goodsOrderNums = orderForGoodsDetaile.getGoodsOrderNums();
            Integer goodsId = orderForGoodsDetaile.getGoodsId();
            Goods byId = goodsService.getById(goodsId);
            goodsService.updateGoodsNums(goodsId, byId.getRemainNums() + goodsOrderNums);
        }
    }


    /*
    订单 状态 改变
     */
    // 未付款 -> 已付款               前提: 未付款
    @Override
    public boolean statusToDoPay(Integer ofgId) {
        if (pdOrderStatus(ofgId, OrderStatus.NO_PAY)) {
            return updateOrderStatus(ofgId, OrderStatus.DO_PAY);
        }
        // 修改状态
        return false;
    }


    // 已付款 -> 已发货 也就是 分拣完成   前提: 已付款
    @Override
    public boolean statusToDelivery(Integer ofgId) {
        if (pdOrderStatus(ofgId, OrderStatus.DO_PAY)) {
            return updateOrderStatus(ofgId, OrderStatus.DELIVERY);
        }
        // 修改状态
        return false;
    }


    // 已发货 -> 店家已签收         前提: 已发货
    @Override
    public boolean statusToStoreDoSign(Integer ofgId) {
        if (pdOrderStatus(ofgId, OrderStatus.DELIVERY)) {
            return updateOrderStatus(ofgId, OrderStatus.STORE_DO_SIGN);

        }
        return false;

        // 修改状态
    }

    // 店家已签收 -> 用户已签收         前提: 店家已签收
    @Override
    public boolean statusToUserDoSign(Integer ofgId) {
        if (pdOrderStatus(ofgId, OrderStatus.STORE_DO_SIGN)) {
            return updateOrderStatus(ofgId, OrderStatus.USER_DO_SIGN);
        }
        return false;

        // 修改状态
    }

    // 用户已签收 -> 订单结束         前提: 用户已签收
    @Override
    public boolean statusToEnd(Integer ofgId) {
        if (pdOrderStatus(ofgId, OrderStatus.USER_DO_SIGN)) {
            return updateOrderStatus(ofgId, OrderStatus.ORDER_END);
        }
        return false;

        // 修改状态
    }

    //将订单 修改为 取消
    @Override
    public boolean statusToChanel(Integer ofgId) {
        if (pdOrderStatus(ofgId, OrderStatus.NO_PAY)) {
            return updateOrderStatus(ofgId, OrderStatus.CANCEL_ORDER);
        }
        throw new OrderException("订单状态不是 未支付");
    }

    // 将状态 修改 未 异常
    @Override
    public boolean statusToError(Integer ofgId) {
        // 修改状态
        return updateOrderStatus(ofgId, OrderStatus.ORDER_ERROR);
    }


    //判断 订单 状态的   前提
    private boolean pdOrderStatus(Integer ofgId, Integer status) {
        OrderForGoods orderForGoods = orderForGoodsMapper.selectByOfgId(ofgId);
        System.out.println(orderForGoods);
        boolean equals = Objects.equals(orderForGoods.getStatus(), status);
        System.out.println("前提状态" + status + "实际状态" + orderForGoods.getStatus() + equals);
        return equals;
    }


    // 只允许 里面 调用
    private boolean updateOrderStatus(Integer ofgId, Integer status) {
        // 更新 订单状态
        if (!orderForGoodsMapper.updateStatusById(ofgId, status)) {
            throw new RuntimeException("更新 订单状态失败");
        }

        // 增加记录表
        OrderRecord orderRecord = new OrderRecord();
        orderRecord.setOfgId(ofgId);
        orderRecord.setStatus(status);
        if (!orderRecordService.save(orderRecord)) {
            throw new RuntimeException("增加记录表 失败");
        }
        return true;
    }


    /**
     * 判断 要修改的状态值 是否合理
     *
     * @param orderStatus 状态值
     * @return
     */
    private boolean statusLimit(Integer orderStatus) {
        return orderStatus >= 0 && orderStatus <= OrderStatus.ORDER_MAX;
    }

}
